
#include <BRender>
#include <BKeyEvent>
#include <BMouseEvent>
#include <BSphereHandler>

#include <BCamera>
#include <BViewer>
#include <BShape>
#include <BMaterial>
#include <BOpenGL>
#include <BSystem>
#include <BMesh>
#include <BSphere>

#include "MainHandler.h"

MainHandler::MainHandler()
{
	_dragHandler = new DragHandler();
	_leftPressed = false;
	_spaceShown = true;
}
MainHandler::~MainHandler()
{

}

void MainHandler::setGridSurface(BSurface* surface)
{
	_gridSurface = surface;
}
BSurface* MainHandler::gridSurface() const
{
	return _gridSurface;
}

void MainHandler::drawPickedFeature(BRender& render, BPickItem* item)
{
	BNode* node = item->node();
	if (BMesh* mesh = dynamic_cast<BMesh*>(item->shape()))
	{
		int index = item->index();
		BTriangle triangle = mesh->triangle(index);
		render.fillTriangle(triangle);
	}
	else if (BGeometry* geometry = dynamic_cast<BGeometry*>(item->shape()))
	{
		BVectorArray* vertices = geometry->vertices();
		BElement* element = item->element();
		if (!element)
			return;
		int index = item->index();
		if (element->primitive() == Primitive_Polygon)
		{
			if (BIndexArray* indices = element->indices())
			{
				render.fillPolygon(*vertices, *indices);
			}
			else if (BPieceArray* pieces = element->pieces())
			{

			}
			else
			{
				int first = element->first();
				int count = element->count();
				render.fillPolygon(vertices->data() + first, count);
			}
		}
		else if (element->primitive() == Primitive_Triangles)
		{
			if (BIndexArray* indices = element->indices())
			{
				int ia = indices->at(index);
				int ib = indices->at(index + 1);
				int ic = indices->at(index + 2);
				const BVector& va = vertices->at(ia);
				const BVector& vb = vertices->at(ib);
				const BVector& vc = vertices->at(ic);
				render.fillTriangle(va, vb, vc);
			}
			else if (BPieceArray* pieces = element->pieces())
			{
				index *= 3;
				int ia = pieces->at(index).v();
				int ib = pieces->at(index + 1).v();
				int ic = pieces->at(index + 2).v();
				const BVector& va = vertices->at(ia);
				const BVector& vb = vertices->at(ib);
				const BVector& vc = vertices->at(ic);
				render.fillTriangle(va, vb, vc);
			}
			else
			{
				int i = element->first() + index * 3;
				const BVector& va = vertices->at(i);
				const BVector& vb = vertices->at(i + 1);
				const BVector& vc = vertices->at(i + 2);
				render.fillTriangle(va, vb, vc);
			}
		}
		else if (element->primitive() == Primitive_Quads)
		{
			if (BIndexArray* indices = element->indices())
			{
				int ia = indices->at(index);
				int ib = indices->at(index + 1);
				int ic = indices->at(index + 2);
				int id = indices->at(index + 3);
				const BVector& va = vertices->at(ia);
				const BVector& vb = vertices->at(ib);
				const BVector& vc = vertices->at(ic);
				const BVector& vd = vertices->at(id);
				render.fillQuad(va, vb, vc, vd);
			}
			else if (BPieceArray* pieces = element->pieces())
			{
				index *= 3;
				int ia = pieces->at(index).v();
				int ib = pieces->at(index + 1).v();
				int ic = pieces->at(index + 2).v();
				int id = pieces->at(index + 3).v();
				const BVector& va = vertices->at(ia);
				const BVector& vb = vertices->at(ib);
				const BVector& vc = vertices->at(ic);
				const BVector& vd = vertices->at(id);
				render.fillQuad(va, vb, vc, vd);
			}
			else
			{
				int i = element->first() + index * 3;
				const BVector& va = vertices->at(i);
				const BVector& vb = vertices->at(i + 1);
				const BVector& vc = vertices->at(i + 2);
				const BVector& vd = vertices->at(i + 3);
				render.fillQuad(va, vb, vc, vd);
			}
		}
	}
}

void MainHandler::render(BRender& render)
{
	if (_hoveredNode)
	{
		render.setLighting(false);
		render.setColor(255, 255, 255);
		render.drawSpace(_hoveredNode->space());
		if (_hoveredShape)
		{
			BBox box = _hoveredShape->box() * _hoveredShape->matrix() * _hoveredNode->matrix();
			render.setLineWidth(1);
			render.setColor(100, 255, 100);
			render.drawBox(box);
			if (_hoveredItem)
			{
				render.pushMatrix();
				render.setMatrix(_hoveredShape->matrix() * _hoveredNode->matrix());
				render.setLighting(false);
				render.setDepthTest(false);
				render.setColor(200, 100, 0);
				drawPickedFeature(render, _hoveredItem);
				render.popMatrix();
			}
		}
	}
	else
	{
		if (_hoveredShape)
		{
			BBox box = _hoveredShape->box() * _hoveredShape->matrix();
			render.setLighting(false);
			render.setLineWidth(1);
			render.setColor(100, 255, 100);
			render.drawBox(box);
		}
	}
	if (_selectedNode)
	{
		render.setLighting(false);
		render.setLineSmooth(true);
		render.setColor(255, 255, 255);

		render.setLineWidth(1);
		render.setLineStipple(0xf0f0);
		render.setDepthTest(true);
		render.drawSpace(_selectedNode->space());
		render.setLineStipple(0);

		render.setLineWidth(2);
		render.setDepthTest(true);
		render.setColor(255, 255, 255);
		//render.drawSpace(node->space());
		render.drawBox(_selectedNode->box() * _selectedNode->matrix());
		for (int s = 0; s < _selectedNode->shapeCount(); s++)
		{
			BShape* shape = _selectedNode->shape(s);
			BBox box = shape->box() * shape->matrix() * _selectedNode->matrix();
			render.setColor(100, 255, 100);
			render.drawBox(box);
		}
	}
}

void MainHandler::attachEvent(const BEvent& event)
{
	
}
void MainHandler::detachEvent(const BEvent& event)
{
	
}

void MainHandler::updateEvent(const BEvent& event)
{
	if (_selectedNode)
	{
		if (_transStep > 0)
		{
			BVector center = this->camera()->center();
			BVector dest = _selectedNode->space().center();
			this->camera()->setCenter(center + (dest - center) / _transStep);
			_transStep--;
			if (_transStep == 0)
			{
				this->camera()->setCenter(dest);
			}
		}
	}
}
void MainHandler::freshEvent(const BEvent& event)
{

}

bool MainHandler::keyDownEvent(const BKeyEvent& event)
{
	if (event.key() == Key_Space)
	{
		if (_selectedNode)
		{
			_transStep = 10;
		}
		return true;
	}
	if (event.key() == Key_LAlt)
	{
		this->addChild(_dragHandler);
		return true;
	}
	if (event.key() == Key_Delete && _selectedNode)
	{
		BScene* scene = this->viewer()->scene();
	}
	return false;
}
bool MainHandler::keyUpEvent(const BKeyEvent& event)
{
	if (event.key() == Key_LAlt)
	{
		this->removeChild(_dragHandler);
		return true;
	}
	return false;
}

bool MainHandler::mouseEnterEvent(const BMouseEvent& event)
{
	return BSphereHandler::mouseEnterEvent(event);
}
bool MainHandler::mouseLeaveEvent(const BMouseEvent& event)
{
	return BSphereHandler::mouseLeaveEvent(event);
}
bool MainHandler::mousePressEvent(const BMouseEvent& event)
{
	if (event.button() == Button_Left)
	{
		const BPoint& pos = event.pos();
		BLine line = this->viewer()->line(pos);
		_leftPressed = true;
		_linePressed = line;
		{
			bool ctrlPressed = BSystem::KeyState(Key_LCtrl);
			BScene* scene = this->viewer()->scene();
			this->fresh();
		}
	}
	return BSphereHandler::mousePressEvent(event);
}
bool MainHandler::mouseReleaseEvent(const BMouseEvent& event)
{
	if (_leftPressed)
	{
		const BPoint& pos = event.pos();
		BLine line = this->viewer()->line(pos);
		_leftPressed = false;
	}
	return BSphereHandler::mouseReleaseEvent(event);
}
bool MainHandler::mouseMoveEvent(const BMouseEvent& event)
{
	const BPoint& pos = event.pos();
	BLine line = this->viewer()->line(pos);
	if (event.button() == Button_None)
	{
		const BPoint& pos = event.pos();
		BLine line = this->viewer()->line(pos);
		BPicker picker(line);
		BNode* hoveredNode = 0;
		BShape* hoveredShape = 0;
		_hoveredItem = this->viewer()->pick(pos);
		if (_hoveredItem)
		{
			_hoveredPoint = _hoveredItem->absolutePoint();
			hoveredNode = _hoveredItem->node();
			hoveredShape = _hoveredItem->shape();
		}
		if (_hoveredNode != hoveredNode || _hoveredShape != hoveredShape)
		{
			_hoveredNode = hoveredNode;
			_hoveredShape = hoveredShape;
			this->fresh();
		}
	}
	return BSphereHandler::mouseMoveEvent(event);
}

